#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import base64
import os
import pytest
import allure
from py.xml import html
from selenium import webdriver

from config.conf import cm
from common.readconfig import ini
from utils.times import timestamp
from utils.send_mail import send_report

driver = None

# 测试框架pytest的胶水文件，用到fixture方法，封装并传递出了driver。
@pytest.fixture(scope='session', autouse=True)
def drivers(request):
    global driver
    if driver is None and cm.INIT_MODE is None:
        print(cm.INIT_MODE)
        # 默认为chrome浏览器
        driver = webdriver.Chrome()
        driver.maximize_window()
        driver.implicitly_wait(5)

    elif driver is None and cm.INIT_MODE == "debug":
        print(cm.INIT_MODE)
        # 声明 chrome 的参数
        chrome_arg = webdriver.ChromeOptions()
        # 加入调试地址
        chrome_arg.debugger_address = '127.0.0.1:9222'
        driver = webdriver.Chrome(options=chrome_arg)
        # driver.maximize_window()
        driver.implicitly_wait(5)
        driver.get(ini.url)

    def fn():
        driver.quit()

    request.addfinalizer(fn)
    return driver


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item):
    """
    当测试失败的时候，自动截图，展示到html报告中
    :param item:
    """
    pytest_html = item.config.pluginmanager.getplugin('html')
    outcome = yield
    report = outcome.get_result()
    report.description = str(item.function.__doc__)
    extra = getattr(report, 'extra', [])

    if report.when == 'call' or report.when == "setup":
        xfail = hasattr(report, 'wasxfail')
        if (report.skipped and xfail) or (report.failed and not xfail):
            screen_img = _capture_screenshot()
            if screen_img:
                html = '<div><img src="datas:image/png;base64,%s" alt="screenshot" style="width:1024px;height:768px;" ' \
                       'onclick="window.open(this.src)" align="right"/></div>' % screen_img
                extra.append(pytest_html.extras.html(html))
        report.extra = extra


def pytest_html_results_table_header(cells):
    cells.insert(1, html.th('用例名称'))
    cells.insert(2, html.th('Test_nodeid'))
    cells.pop(2)


def pytest_html_results_table_row(report, cells):
    if hasattr(report, 'description'):
        td1 = html.td(report.description)
    else:
        td1 = ''
    cells.insert(1, td1)
    cells.insert(2, html.td(report.nodeid))
    cells.pop(2)


def pytest_html_results_table_html(report, data):
    if report.passed:
        del data[:]
        data.append(html.div('通过的用例未捕获日志输出.', class_='empty log'))


def pytest_html_report_title(report):
    report.title = "飞书项目Html测试报告"


def pytest_configure(config):
    config._metadata.clear()
    config._metadata['测试项目'] = "测试百度官网搜索"
    config._metadata['测试地址'] = ini.url


def pytest_html_results_summary(prefix, summary, postfix):
    # prefix.clear() # 清空summary中的内容
    prefix.extend([html.p("所属部门: XX公司测试部")])
    prefix.extend([html.p("测试执行人: 随风挥手")])


def pytest_terminal_summary(terminalreporter, exitstatus, config):
    """收集测试结果"""
    result = {
        "total": terminalreporter._numcollected,
        'passed': len(terminalreporter.stats.get('passed', [])),
        'failed': len(terminalreporter.stats.get('failed', [])),
        'error': len(terminalreporter.stats.get('error', [])),
        'skipped': len(terminalreporter.stats.get('skipped', [])),
        # terminalreporter._sessionstarttime 会话开始时间
        'total times': timestamp() - terminalreporter._sessionstarttime
    }
    print(result)
    # 验证运行测试用例失败会自动截图和发送邮件
    if result['failed'] or result['error']:
        send_report()


def _capture_screenshot():
    """截图保存为base64"""
    """
    webdriver截图生成文件，并使用allure.attach.file方法将文件添加到了allure测试报告中,
    返回base64编码，同时生效pytest-html 和 allure, 一次运行可得到简单和丰富的2份报告。
    :return:
    """
    now_time, screen_file = cm.screen_path
    if driver:
        driver.save_screenshot(screen_file)
        allure.attach.file(screen_file,"失败截图{}".format(now_time), allure.attachment_type.PNG)
        with open(screen_file, 'rb') as f:
            imagebase64 = base64.b64encode(f.read())
        return imagebase64.decode()